/**
 * @author Daniel
 *
 * @required kinetic-v4.0.5.js
 * @required jquery.extension.js
 */

(function($) {
	
	var Action = {};
	
	Action.Type = {
		beginDrawRect: 'beginDrawRect'
		, drawingRect: 'drawingRect'
		, insertImage: 'insertImage'
		, dragImage: 'dragImage'
		, beginDrawBrush: 'beginDrawBrush'
		, drawingBrush: 'drawingBrush'
		, beginDrawLine: 'beginDrawLine'
		, drawingLine: 'drawingLine'
		, beginDrawSquare: 'beginDrawSquare'
		, drawingSquare: 'drawingSquare'
		, beginDrawCircle: 'beginDrawCircle'
		, drawingCircle: 'drawingCircle'
		, beginDrawEllipse: 'beginDrawEllipse'
		, drawingEllipse: 'drawingEllipse'
		, displayTextBox: 'displayTextBox'
		, displayText: 'displayText'
		, dragText: 'dragText'
		, undo: 'undo'
		, beginErase: 'beginErase'
		, erasing: 'erasing'
	};
	
	Action.BeginDrawRect = function(x, y, fill, stroke, strokeWidth, targetId) {
	    this.type = Action.Type.beginDrawRect;
	    this.targetId = targetId;
	    this.x = x;
	    this.y = y;
	    this.fill = fill;
		this.stroke = stroke;
		this.strokeWidth = strokeWidth;
		this.time = new Date().getTime();		
	};
	Action.DrawingRect = function(x, y, targetId) {
	    this.type = Action.Type.drawingRect;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();			
	};
	Action.BeginDrawSquare = function(x, y, fill, stroke, strokeWidth, targetId) {
	    this.type = Action.Type.beginDrawSquare;
	    this.targetId = targetId;
	    this.x = x;
	    this.y = y;
	    this.fill = fill;
		this.stroke = stroke;
		this.strokeWidth = strokeWidth;
		this.time = new Date().getTime();		
	};
	Action.DrawingSquare = function(x, y, targetId) {
	    this.type = Action.Type.drawingSquare;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();			
	};
	Action.BeginDrawCircle = function(x, y, fill, stroke, strokeWidth, targetId) {
	    this.type = Action.Type.beginDrawCircle;
	    this.targetId = targetId;
	    this.x = x;
	    this.y = y;
	    this.fill = fill;
		this.stroke = stroke;
		this.strokeWidth = strokeWidth;
		this.time = new Date().getTime();		
	};
	Action.DrawingCircle = function(x, y, targetId) {
	    this.type = Action.Type.drawingCircle;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();			
	};	
	Action.BeginDrawEllipse = function(x, y, fill, stroke, strokeWidth, targetId) {
	    this.type = Action.Type.beginDrawEllipse;
	    this.targetId = targetId;
	    this.x = x;
	    this.y = y;
	    this.fill = fill;
		this.stroke = stroke;
		this.strokeWidth = strokeWidth;
		this.time = new Date().getTime();		
	};
	Action.DrawingEllipse = function(x, y, targetId) {
	    this.type = Action.Type.drawingEllipse;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();			
	};	
	Action.BeginDrawBrush = function(x, y, stroke, strokeWidth, targetId) {
	    this.type = Action.Type.beginDrawBrush;
	    this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.stroke = stroke;
		this.strokeWidth = strokeWidth;
		this.time = new Date().getTime();			
	};
	Action.DrawingBrush = function(x, y, targetId) {
	    this.type = Action.Type.drawingBrush;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();		
	};
	Action.BeginDrawLine = function(x, y, stroke, strokeWidth, targetId) {
	    this.type = Action.Type.beginDrawLine;
	    this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.stroke = stroke;
		this.strokeWidth = strokeWidth;
		this.time = new Date().getTime();			
	};
	Action.DrawingLine = function(x, y, targetId) {
	    this.type = Action.Type.drawingLine;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();		
	};
	Action.InsertImage = function(x, y, url, targetId, noSendRemote) {
	    this.type = Action.Type.insertImage;
		this.targetId = targetId;
		this.url = url;
	    this.x = x;
	    this.y = y;
	    this.noSendRemote = noSendRemote;
		this.time = new Date().getTime();			
	};
	Action.DragImage = function(x, y, targetId) {
	    this.type = Action.Type.dragImage;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();		
	};
	Action.DisplayTextBox = function(x, y, text, textColor, fontSize) {
	    this.type = Action.Type.displayTextBox;
		this.text = text;
		this.textColor = textColor;
		this.fontSize = fontSize;
	    this.x = x;
	    this.y = y;
	    this.noSendRemote = true;
		this.time = new Date().getTime();		
	};
	Action.DisplayText = function(x, y, text, textColor, fontSize, targetId) {
	    this.type = Action.Type.displayText;
	    this.text = text;
		this.targetId = targetId;
		this.textColor = textColor;
		this.fontSize = fontSize;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();		
	};
	Action.DragText = function(x, y, targetId) {
	    this.type = Action.Type.displayText;
		this.targetId = targetId;
	    this.x = x;
	    this.y = y;
		this.time = new Date().getTime();			
	};
	Action.Undo = function(layerId) {
	    this.type = Action.Type.undo;
	    this.layerId = layerId;
		this.time = new Date().getTime();		
	};
	Action.BeginErase = function(x, y, width, height) {
	    this.type = Action.Type.beginErase;
	    this.x = x;
	    this.y = y;
	    this.width = width;
	    this.height = height;
		this.time = new Date().getTime();			
	};
	Action.Erasing = function(x, y, width, height) {
	    this.type = Action.Type.erasing;
	    this.x = x;
	    this.y = y;
	    this.width = width;
	    this.height = height;
		this.time = new Date().getTime();			
	};
	
	var dwb = {
		options: {
			
		}
		
		, events: {
			newAction: 'newAction'
		}
		
		, _const: {
			
		}
		
		, _stage: null
		
		, _layer: null
		
		, _isMouseDown: false
		
		, _mouseDownX: 0
		
		, _mouseDownY: 0
		
		, _fillColor: 'yellow'
		
		, _strokeColor: 'orange'
		
		, _strokeWidth: 1
		
		, _fontSize: 12
		
		, _eraserWidth: 15
		
		, _eraserHeight: 15
		
		, _draggable: false
		
		, _actions: []
		
		, _tmpCanvas: null //用于优化画形状性能
		
		, _stepLayersCanvases: {} //存储所有层(所有人)的每次画完形状时的canvas 
		
		, _create: function() {
			var self = this;
			var container = self.element;
			
			self._stage = new Kinetic.Stage({
					container : container.get(0)
					, width : container.width()
					, height : container.height()
			});
			self._layer = new Kinetic.Layer({id:'myLayer'});
			self._stage.add(self._layer);
			
			self._bindEvents();
		}
		
		, _cloneCanvas: function(canvas) {
			var newCanvas = document.createElement("canvas");
			var context = newCanvas.getContext('2d');
	        newCanvas.width = canvas.width;
	        newCanvas.height = canvas.height;
	        context.drawImage(canvas, 0, 0); 
	        return newCanvas;
		}
		
		, _cloneToTmpCanvas: function(canvas, layerId) {
			var self = this;
			if (!self._tmpCanvas) {
				self._tmpCanvas = document.createElement("canvas");
			}
			var tmpContext = self._tmpCanvas.getContext('2d');
	        self._tmpCanvas.width = canvas.width;
	        self._tmpCanvas.height = canvas.height;
	        tmpContext.drawImage(canvas, 0, 0); 
	        
	        if (!self._stepLayersCanvases.hasOwnProperty(layerId)) {
	        	self._stepLayersCanvases[layerId] = [];
	        }
	        self._stepLayersCanvases[layerId].push(self._cloneCanvas(canvas)); 
		}
		
		/**
		 * 重画形状，取代layer.drow()方法
		 * kinetic的layer.drow()方法实现机制是遍历所有子元素然后一个一个画，性能太低，
		 * 这里的实现机制是先将画之前的canvas保存起来，当在画的过程中，将之前的canvas显示出来，然后只画最后一步，性能大大提升
		 */
		, _redrawShape: function(layer, shape) {
			var self = this;
			layer.getContext().clearRect(0, 0, layer.getCanvas().getWidth(), layer.getCanvas().getHeight());
			layer.getContext().drawImage(self._tmpCanvas, 0, 0);
			shape.draw(layer.getCanvas());			
		}
		
		, _bindEvents: function() {
			var self = this;
			var container = self.element;	
			var resizeTimeout;
			
			container.bind({
				'mousedown': function(event) {
					self._isMouseDown = true;
				}
				, 'mouseup': function(event) {
					self._isMouseDown = false;
				}
			});
			
			$(window).resize(function(){
				clearTimeout(resizeTimeout);
				resizeTimeout = setTimeout(function() {
				    self._stage.setWidth(container.width());
				    self._stage.setHeight(container.height());
				}, 150);
			});
		}
		
		/**
		 * @param isPlay: 是否播放，当本地回放或者播放远程的动作时为true
		 * @param callback: 执行后的回调函数，以下动作会调用：
		 * 1.Action.Type.insertImage, 返回创建的Kinetic.Image对象
		 */
		, _execute: function(action, isPlay, callback, layer) {
			var self = this;
			var container = self.element;	
			
			self._actions.push(action);
			if (!isPlay) {
				if (!action.noSendRemote) {
					self._trigger(self.events.newAction, new $.Event(self.events.newAction), action);
				} 
			}
			
			if (action.type == Action.Type.beginDrawRect) {
				self._mouseDownX = action.x;
				self._mouseDownY = action.y;
				var rect = new Kinetic.Rect({
								x: self._mouseDownX
								, y: self._mouseDownY
								, width: 0
								, height: 0
								, fill: action.fill
								, stroke: action.stroke
								, strokeWidth: action.strokeWidth 
								, draggable: self._draggable
								, id: action.targetId
							});	
							
				layer.add(rect);
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
			} 
			else if (action.type == Action.Type.drawingRect) {
				var rect = self._stage.get('#'+action.targetId)[0];
				rect.setWidth(action.x - self._mouseDownX);
				rect.setHeight(action.y - self._mouseDownY);
				
				self._redrawShape(layer, rect);			
			}
			else if (action.type == Action.Type.beginDrawSquare) {
				self._mouseDownX = action.x;
				self._mouseDownY = action.y;
				var square = new Kinetic.Rect({
								x: self._mouseDownX
								, y: self._mouseDownY
								, width: 0
								, height: 0
								, fill: action.fill
								, stroke: action.stroke
								, strokeWidth: action.strokeWidth 
								, draggable: self._draggable
								, id: action.targetId
							});	
							
				layer.add(square);
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
			} 
			else if (action.type == Action.Type.drawingSquare) {
				var square = self._stage.get('#'+action.targetId)[0];
				var width = action.x - self._mouseDownX;
				var height = action.y - self._mouseDownY;
				square.setWidth(width);
				square.setHeight(height < 0 ? -Math.abs(width) : Math.abs(width));
				
				self._redrawShape(layer, square);		
			}
			else if (action.type == Action.Type.beginDrawCircle) {
				self._mouseDownX = action.x;
				self._mouseDownY = action.y;
				var circle = new Kinetic.Circle({
								x: self._mouseDownX
								, y: self._mouseDownY
								, radius: 0
								, fill: action.fill
								, stroke: action.stroke
								, strokeWidth: action.strokeWidth 
								, draggable: self._draggable
								, id: action.targetId
							});	
							
				layer.add(circle);
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
			} 
			else if (action.type == Action.Type.drawingCircle) {
				var a = action.x - self._mouseDownX;
				var b = action.y - self._mouseDownY;
				var radius = Math.sqrt(a*a + b*b);
				var circle = self._stage.get('#'+action.targetId)[0];
				circle.setRadius(radius);
					   
				self._redrawShape(layer, circle);
			}
			else if (action.type == Action.Type.beginDrawEllipse) {
				self._mouseDownX = action.x;
				self._mouseDownY = action.y;
				var ellipse = new Kinetic.Ellipse({
								x: self._mouseDownX
								, y: self._mouseDownY
								, radius: {x: 0, y: 0}
								, fill: action.fill
								, stroke: action.stroke
								, strokeWidth: action.strokeWidth 
								, draggable: self._draggable
								, id: action.targetId
							});	
							
				layer.add(ellipse);
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
			} 
			else if (action.type == Action.Type.drawingEllipse) {
				var x = Math.abs(action.x - self._mouseDownX);
				var y = Math.abs(action.y - self._mouseDownY);
				var ellipse = self._stage.get('#'+action.targetId)[0];
				ellipse.setRadius({x:x==0?1:x, y:y==0?1:y});
				
				self._redrawShape(layer, ellipse);			
			}
			else if (action.type == Action.Type.beginDrawBrush) {
				var line = new Kinetic.Line({
					points: [action.x, action.y]
					, stroke: action.stroke
					, strokeWidth: action.strokeWidth
					, lineCap: "round"
					, lineJoin: "round"
					, id: action.targetId
				});
							
				layer.add(line);
				
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
				self._redrawShape(layer, line);
			} 
			else if (action.type == Action.Type.drawingBrush) {
				var line = self._stage.get('#'+action.targetId)[0];
				line.drawSmallStep(action.x, action.y);
			}
			else if (action.type == Action.Type.beginDrawLine) {
				var line = new Kinetic.Line({
					points: [action.x, action.y]
					, stroke: action.stroke
					, strokeWidth: action.strokeWidth
					, lineCap: "round"
					, lineJoin: "round"
					, id: action.targetId
				});
							
				layer.add(line);
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
			} 
			else if (action.type == Action.Type.drawingLine) {
				var line = self._stage.get('#'+action.targetId)[0];
				line.setPoints($.merge([line.getPoints()[0]], [{x:action.x, y:action.y}]));
				
				self._redrawShape(layer, line);			
			}
			else if (action.type == Action.Type.insertImage) {
				var imageObj = new Image();
				imageObj.onload = function() {
					self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
					var img = self._stage.get('#'+action.targetId);
					if (img.length > 0) {
						img = img[0];
						img.setImage(imageObj);
						img.setWidth(imageObj.width);
						img.setHeight(imageObj.height);
					} else {
						img = new Kinetic.Image({
							x: action.x
							, y: action.y
							, image: imageObj
							, width: imageObj.width
							, height: imageObj.height
							, id: action.targetId
							, draggable: true
						});
						layer.add(img);
						self._redrawShape(layer, img);
						if (callback && typeof(callback) == 'function') {
							callback(img);
						}
					}
				}
				imageObj.src = action.url;	
			}
			else if (action.type == Action.Type.dragImage) {
				var img = self._stage.get('#'+action.targetId)[0];
				if (img.attrs.x != action.x && img.attrs.y != action.y) {
					img.setX(action.x);
					img.setY(action.y);
					self._redrawShape(layer, img);			
				}
			}
			else if (action.type == Action.Type.displayTextBox) {
				var textbox = $('<div class="textbox"><input type="text" /></div>');
				var textinput = textbox.find('input[type="text"]');
				$('body').append(textbox);
				
				var displayText = function() {
					var textId = $.createUID();
					var text = textinput.val();
					textbox.remove();
					if (text) {
						action = new Action.DisplayText(action.x, action.y, text, action.textColor, action.fontSize, textId);
						self._execute(action, isPlay, callback, layer);
					}
				};
				
				textbox.css({left:action.x, top:action.y});
				textinput.focus();
				textinput.bind({
					'keydown': function(event) {
				    	if (event.keyCode == 13) {
				    		displayText();
				    	}
					}
					, 'blur': function() {
						displayText();
					}
				});
			}
			else if (action.type == Action.Type.displayText) {
				 var text = new Kinetic.Text({
			        x: action.x
			        , y: action.y
			        , text: action.text
			        , textFill: action.textColor
			        , fontSize: action.fontSize
			        , id: action.targetId
			      });
				layer.add(text);
				
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
				self._redrawShape(layer, text);
			}
			else if (action.type == Action.Type.undo) {
				var canvases = self._stepLayersCanvases[action.layerId];
				if (canvases.length > 0) {
					layer.getContext().clearRect(0, 0, layer.getCanvas().getWidth(), layer.getCanvas().getHeight());
					layer.getContext().drawImage(canvases.pop(), 0, 0);
				}
			}
			else if (action.type == Action.Type.beginErase) {
				self._cloneToTmpCanvas(layer.getCanvas().getElement(), layer.getId()); //将当前的canvas保存起来
				
				var layers = self._stage.children;
				$.each(layers, function(idx, layerItem) {
					layerItem.getContext().clearRect(action.x, action.y, action.width, action.height);
				});
			}
			else if (action.type == Action.Type.erasing) {
				var layers = self._stage.children;
				$.each(layers, function(idx, layerItem) {
					layerItem.getContext().clearRect(action.x, action.y, action.width, action.height);
				});
			}
		}
		
		/**
		 * @param n: 第几个动作
		 * @param actions: 全部动作 
		 * @param layer: 层
		 * @param fastForward: 是否快进
		 */
		, _playback: function(n, actions, layer, fastForward) {
			var self = this;
			n = n ? n : 0;
			
			if (actions.length == 0 ||  actions.length <= n) {
				return;
			}
			
			var action = actions[n];
			self._execute(action, true, null, layer);
			
			if (actions.length == n+1) {
				return;
			}
			
			var nextAction = actions[n+1];
			var interval = fastForward ? 0 : nextAction.time - action.time;
			setTimeout(function() {$.proxy(self._playback(n+1, actions, layer, fastForward), self);}, interval);
		}
		
		, _disableDraw: function() {
			var self = this;
			var container = self.element;
			container.unbind('mousedown.dwb');	
			container.unbind('mousemove.dwb');	
			container.unbind('click.dwb');
		}
		
		, activeRectDraw: function() {
			var self = this;
			var container = self.element;		
			var rectId;
			
			self._disableDraw();
				
			container.bind({
				'mousedown.dwb.rect': function(event) {
					rectId = $.createUID();
					var action = new Action.BeginDrawRect(event.clientX, event.clientY, self._fillColor, self._strokeColor, self._strokeWidth, rectId);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.rect': function(event) {
					if (self._isMouseDown) {
						var action = new Action.DrawingRect(event.clientX, event.clientY, rectId);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});			
		}
		
		, activeSquareDraw: function() {
			var self = this;
			var container = self.element;		
			var squareId;
			
			self._disableDraw();
				
			container.bind({
				'mousedown.dwb.square': function(event) {
					squareId = $.createUID();
					var action = new Action.BeginDrawSquare(event.clientX, event.clientY, self._fillColor, self._strokeColor, self._strokeWidth, squareId);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.square': function(event) {
					if (self._isMouseDown) {
						var action = new Action.DrawingSquare(event.clientX, event.clientY, squareId);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});			
		}
		
		, activeCircleDraw: function() {
			var self = this;
			var container = self.element;		
			var circleId;
			
			self._disableDraw();
				
			container.bind({
				'mousedown.dwb.circle': function(event) {
					circleId = $.createUID();
					var action = new Action.BeginDrawCircle(event.clientX, event.clientY, self._fillColor, self._strokeColor, self._strokeWidth, circleId);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.circle': function(event) {
					if (self._isMouseDown) {
						var action = new Action.DrawingCircle(event.clientX, event.clientY, circleId);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});			
		}
		
		, activeEllipseDraw: function() {
			var self = this;
			var container = self.element;		
			var ellipseId;
			
			self._disableDraw();
				
			container.bind({
				'mousedown.dwb.circle': function(event) {
					ellipseId = $.createUID();
					var action = new Action.BeginDrawEllipse(event.clientX, event.clientY, self._fillColor, self._strokeColor, self._strokeWidth, ellipseId);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.circle': function(event) {
					if (self._isMouseDown) {
						var action = new Action.DrawingEllipse(event.clientX, event.clientY, ellipseId);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});			
		}
		
		, activeBrushDraw: function() {
			var self = this;
			var container = self.element;		
			var brushId;
			
			self._disableDraw();	
			
			container.bind({
				'mousedown.dwb.brush': function(event) {
					brushId = $.createUID();
					var action = new Action.BeginDrawBrush(event.clientX, event.clientY, self._strokeColor, self._strokeWidth, brushId);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.brush': function(event) {
					if (self._isMouseDown) {
						var action = new Action.DrawingBrush(event.clientX, event.clientY, brushId);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});						
		}
		
		, activeLineDraw: function() {
			var self = this;
			var container = self.element;		
			var lineId;
			
			self._disableDraw();	
			
			container.bind({
				'mousedown.dwb.line': function(event) {
					lineId = $.createUID();
					var action = new Action.BeginDrawLine(event.clientX, event.clientY, self._strokeColor, self._strokeWidth, lineId);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.line': function(event) {
					if (self._isMouseDown) {
						var action = new Action.DrawingLine(event.clientX, event.clientY, lineId);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});						
		}
		
		, activeTextDraw: function() {
			var self = this;
			var container = self.element;		
			
			self._disableDraw();	
			
			container.bind({
				'click.dwb.text': function(event) {
					var action = new Action.DisplayTextBox(event.clientX, event.clientY, '', self._strokeColor, self._fontSize);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
			});						
		}
		
		, activeEraser: function() {
			var self = this;
			var container = self.element;		
			
			self._disableDraw();
				
			container.bind({
				'mousedown.dwb.eraser': function(event) {
					rectId = $.createUID();
					var action = new Action.BeginErase(event.clientX, event.clientY, self._eraserWidth, self._eraserHeight);
					$.proxy(self._execute(action, false, null, self._layer), self);
				}
				, 'mousemove.dwb.eraser': function(event) {
					if (self._isMouseDown) {
						var action = new Action.Erasing(event.clientX, event.clientY, self._eraserWidth, self._eraserHeight);
						$.proxy(self._execute(action, false, null, self._layer), self);				
					}
				}
			});			
		}		
		
		/**
		 * @param imgUrl
		 * @param imgIdOrCallback imgId or callbackFun (通过回调函数返回imgId)
		 */
		, insertImage: function(imgUrl, imgIdOrCallback) {
			var self = this;
			var container = self.element;		
			var imgId, callbackFun = null, exeCallback = null;
			var x = 140; //TODO
			var y = self._stage.getHeight() / 2; //TODO
			var img = self._stage.get('#'+imgId);
			
			if (imgIdOrCallback) {
				if (typeof(imgIdOrCallback) == 'function') {
					imgId = $.createUID();
					callbackFun = imgIdOrCallback;
				} else {
					imgId = imgIdOrCallback;
				}
			} else {
				imgId = $.createUID();
			}
			
			self._disableDraw();

			if (img.length == 0) {
				exeCallback = function(img) {
					if (callbackFun) {
						callbackFun(img.getId());
					}
					img.on("dragmove", function() {
						self._disableDraw();
						var action = new Action.DragImage(img.attrs.x, img.attrs.y, imgId);
						$.proxy(self._execute(action, false, null, self._layer), self);
					});
				}
			}

			var action = new Action.InsertImage(x, y, imgUrl, imgId, false);
	        var regex = new RegExp('^(data|blob)');
	        var results = regex.exec(imgUrl);
	        if (results != null) { //本地图片
	            action = new Action.InsertImage(x, y, imgUrl, imgId, true);
	        }
	        
			self._execute(action, false, exeCallback, self._layer);
		}
		
		, undo: function() {
			var self = this;
			var action = new Action.Undo(self._layer.getId());
			self._execute(action, false, null, self._layer);
		}
		
		/**
		 * @actions: 播放的动作数组，当为null时为本地回放
		 * @layerId: 层ID,指明要在哪个层画,当多个对战时可避免干扰
		 * @fastForward(boolean): 是否快进播放,default is false 
		 */
		, playback: function(actions, layerId, fastForward) {
			var self = this;
			var layer = self._layer;
			
			if (!actions) {
				self._disableDraw();
				self._stage.reset();
				self._stage.add(self._layer);
				actions = $.merge([], self._actions);
				self._actions = [];
			} 
			else {
				if (layerId) {
					if (self._stage.get('#'+layerId).length > 0) { //exist
						layer = self._stage.get('#'+layerId)[0];
					}
					else {
						layer = new Kinetic.Layer({id:layerId});
						self._stage.add(layer);
					}
				}
			}
			
			fastForward = fastForward == undefined ? false : fastForward;
			self._playback(0, actions, layer, fastForward);			
		}
		
		, toImage: function(callback) {
			var self = this;
			self._stage.toImage({
				callback: function(img) {
					callback(img);
				}
			});
		}
		
		, setFillColor: function(colorVal) {
			this._fillColor = colorVal;
		}
		
		, setStrokeColor: function(colorVal) {
			this._strokeColor = colorVal;
		}
		
		, setStrokeWidth: function(widthVal) {
			if (typeof(widthVal) == 'string') {
				widthVal = parseInt(widthVal);
			}
			this._strokeWidth = widthVal;
		}
		
		, setFontSize: function(fontSize) {
			if (typeof(fontSize) == 'string') {
				fontSize = parseInt(fontSize);
			}
			this._fontSize = fontSize;
		}
		
		, setEraserSize: function(width, height) {
			this._eraserWidth = width;
			this._eraserHeight = height;
		}
		
		, setDraggable: function(draggable) {
			this._draggable = draggable;
		}
		
		, destroy: function() {
			var self = this;
			$.Widget.prototype.destroy.call(self);
		}
	};
	
	$.widget('daniel.dwb', dwb);
})(jQuery);
